<?php
declare(strict_types=1);

namespace Zms\Excel;

use Vtiful\Kernel\Excel;
use Zms\Unit\Directory;

class Export
{

    /**
     * 储存位置
     * @var string
     */
    private $save_path = '';

    /**
     * 导出数据
     * @var array
     */
    private $data = [];


    /**
     * 设置文件名
     * @var string
     */
    private $file_name = '';


    /**
     * 文件名是否加随机数量
     * @var bool
     */
    private $random_str = true;


    /**
     * 导出数据列配置
     * @var array{array{string}}
     */
    private $column = [];

    /**
     * 列名称
     */
    const COLUMN_NAME = [
        'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z',
        'AA', 'AB', 'AC', 'AD', 'AE', 'AF', 'AG', 'AH', 'AI', 'AJ', 'AK', 'AL', 'AM', 'AN', 'AO', 'AP', 'AQ', 'AR', 'AS', 'AT', 'AU', 'AV', 'AW', 'AX', 'AY', 'AZ',
    ];

    public function __construct(string $save_path)
    {
        $this->save_path = rtrim($save_path, '/\\');
        $this->file_name = date("YmdHis");
    }


    /**
     * 获取导出文件实例
     * @param string $save_path
     * @return self
     */
    public static function instance(string $save_path): Export
    {
        return new self($save_path);
    }

    /**
     * 设置导出数据
     * @param array{array{string}} $data
     * @return $this
     */
    public function setData(array $data): Export
    {
        $this->data = $data;
        return $this;
    }


    /**
     * 追加数据
     * @param array{string} $row
     * @return $this
     */
    public function appendData(array $row): Export
    {
        $this->data[] = $row;
        return $this;
    }


    /**
     * 设置导出文件名
     * @param string $file_name
     * @param bool $random_str
     * @return Export
     */
    public function setFileName(string $file_name, bool $random_str = true): Export
    {
        $this->file_name = $file_name;
        $this->random_str = $random_str;
        return $this;
    }


    /**
     * 设置导出列表配置
     * @param array $column
     * @return $this
     */
    public function setColumn(array $column): Export
    {
        $this->column = $column;
        return $this;
    }


    /**
     * 储存文件
     * @return void
     */
    public function save(): string
    {
        $filename = $this->getFileName();
        $excel = new Excel(['path' => dirname($filename)]);
        $excel->fileName(basename($filename), 'sheet1')->setColumn('A1:B1', 500)->header($this->column)->data($this->data);
        $ColumnData = $this->computeColumn($this->data, $this->column);
        foreach ($ColumnData as $index => $len) {
            $column_name = self::COLUMN_NAME[$index];
            $excel->setColumn("{$column_name}1:{$column_name}1", intval($len));
        }
        $filepath = $excel->output();
        if (in_array('close', get_class_methods($excel))) {
            @$excel->close();
        }
        return $filepath;
    }

    /**
     * 生成文件名
     * @return string
     */
    private function getFileName()
    {
        if (!is_dir($this->save_path)) {//目录不存在,先创建目录
            Directory::created($this->save_path);
        }
        $paths = [$this->save_path, DIRECTORY_SEPARATOR];
        $paths[] = $this->file_name ?? date("YmdHis");
        if ($this->random_str) {
            $paths[] = '-';
            $paths[] = rand(1000, 9999);
        }
        $paths[] = '.xlsx';
        return join($paths);
    }


    /**
     * 计算列宽
     * @param array $data
     * @param array $header
     * @return array
     */
    private function computeColumn(array $data, array $header): array
    {
        $ColumnData = [];
        $data[] = $header;
        foreach ($data as $row) {
            foreach ($row as $index => $val) {
                if (!isset($ColumnData[$index])) {
                    $ColumnData[$index] = 0;
                }
                $ColumnData[$index] = max(strlen("{$val}"), $ColumnData[$index]);
            }
        }
        return $ColumnData;
    }

}